package com.zds.support.api.retrofit.body


import android.os.Handler
import android.os.Looper
import android.os.Message
import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*

class ProgressResponseBody : ResponseBody {
    private val MSG_WHAT_UPDATE_PROGRESS = 0X001
    private val responseBody: ResponseBody
    private val progressListener: (bytesRead: Long, contentLength: Long, done: Boolean) -> Unit
    private var bufferedSource: BufferedSource? = null
    private val handler: Handler

    constructor(responseBody: ResponseBody,
                progressListener: (bytesRead: Long, contentLength: Long, done: Boolean) -> Unit) {
        this.responseBody = responseBody
        this.progressListener = progressListener
        handler= object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                if (msg != null) {
                    if (msg.what == MSG_WHAT_UPDATE_PROGRESS) {
                        val obj = msg.obj
                        if (obj!=null &&obj is ProgressUpdateMessage) {
                            progressListener.invoke(obj.bytesRead,obj.contentLength,obj.done)
                        }
                    }
                }
            }
        }

    }

    override fun contentLength(): Long {
        return responseBody.contentLength()
    }

    override fun contentType(): MediaType? {
        return responseBody.contentType()
    }

    override fun source(): BufferedSource {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(source(responseBody.source()))
        }
        return bufferedSource!!
    }

    private fun source(source: Source): Source {
        return object : ForwardingSource(source) {
            var totalBytesRead = 0L
            override fun read(sink: Buffer, byteCount: Long): Long {
                val bytesRead = super.read(sink, byteCount)
                totalBytesRead += if (bytesRead != -1L) bytesRead else 0
                val done = bytesRead == -1L
                val progressMessage =
                        ProgressUpdateMessage(
                                totalBytesRead,
                                responseBody.contentLength(),
                                done
                        )
                val msg = Message()
                msg.what = MSG_WHAT_UPDATE_PROGRESS
                msg.obj = progressMessage
                handler.sendMessage(msg)
                return bytesRead
            }
        }
    }

    private data class ProgressUpdateMessage(val bytesRead: Long = 0,
                                             val contentLength: Long = 0,
                                             val done: Boolean = false)
}